home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / awe2-0_1.lha / awe2-0.1 / Src / RCS / ThreadEventPairingHeap.cc,v < prev    next >
Text File  |  1988-10-12  |  10KB  |  386 lines

  1. head     1.1;
  2. access   ;
  3. symbols  ;
  4. locks    grunwald:1.1; strict;
  5. comment  @@;
  6.  
  7.  
  8. 1.1
  9. date     88.10.12.10.50.43;  author grunwald;  state Exp;
  10. branches ;
  11. next     ;
  12.  
  13.  
  14. desc
  15. @@
  16.  
  17.  
  18.  
  19. 1.1
  20. log
  21. @Initial revision
  22. @
  23. text
  24. @// This may look like C code, but it is really -*- C++ -*-
  25. /* 
  26. Copyright (C) 1988 Free Software Foundation
  27.     written by Dirk Grunwald (grunwald@@cs.uiuc.edu)
  28.     adapted for libg++ by Doug Lea (dl@@rocky.oswego.edu)
  29.  
  30. This file is part of GNU CC.
  31.  
  32. GNU CC is distributed in the hope that it will be useful,
  33. but WITHOUT ANY WARRANTY.  No author or distributor
  34. accepts responsibility to anyone for the consequences of using it
  35. or for whether it serves any particular purpose or works at all,
  36. unless he says so in writing.  Refer to the GNU CC General Public
  37. License for full details.
  38.  
  39. Everyone is granted permission to copy, modify and redistribute
  40. GNU CC, but only under the conditions described in the
  41. GNU CC General Public License.   A copy of this license is
  42. supposed to have been given to you along with GNU CC so you
  43. can know your rights and responsibilities.  It should be in a
  44. file named COPYING.  Among other things, the copyright notice
  45. and this notice must be preserved on all copies.  
  46. */
  47.  
  48.  
  49. #include "stream.h"
  50. #include "ThreadEventPairingHeap.h"
  51. //
  52. //    This defines a Pairing Heap structure for a pointer data type.
  53. //
  54. //    See ``The Pairing Heap: A New Form of Self-Adjusting Heap''
  55. //    Fredman, Segdewick et al,
  56. //    Algorithmica (1986) 1:111-129
  57. //
  58. //    In particular, this implements the pairing heap using the circular
  59. //    list.
  60. //
  61. //
  62.  
  63. #define MIN_STORAGE_SIZE  8
  64.  
  65. // error handling
  66.  
  67.  
  68. void default_ThreadEventPairingHeap_error_handler(char* msg)
  69. {
  70.   cerr << "Fatal ThreadEventPairingHeap error. " << msg << "\n";
  71.   exit(1);
  72. }
  73.  
  74. one_arg_error_handler_t ThreadEventPairingHeap_error_handler = default_ThreadEventPairingHeap_error_handler;
  75.  
  76. one_arg_error_handler_t set_ThreadEventPairingHeap_error_handler(one_arg_error_handler_t f)
  77. {
  78.   one_arg_error_handler_t old = ThreadEventPairingHeap_error_handler;
  79.   ThreadEventPairingHeap_error_handler = f;
  80.   return old;
  81. }
  82.  
  83. void ThreadEventPairingHeap::error(const char* msg)
  84. {
  85.   (*ThreadEventPairingHeap_error_handler)(msg);
  86. }
  87.  
  88. ThreadEventPairingHeap::ThreadEventPairingHeap(int length = 0)
  89. {
  90.   freelist = ThreadEventPairingHeapIndex_NULL;
  91.   root = ThreadEventPairingHeapIndex_NULL;
  92.   allocatedSize = 0;
  93.   elements = 0;
  94.   make_room(length);
  95. }
  96.  
  97. ThreadEventPairingHeapIndex ThreadEventPairingHeap::get_cell()
  98. {
  99.   if (freelist == ThreadEventPairingHeapIndex_NULL)
  100.     make_room(0);
  101.  
  102.   ThreadEventPairingHeapIndex cell = freelist;
  103.   storage[freelist].valid = 1;
  104.   freelist = storage[freelist].sibling;
  105.   elements++;
  106.   return(cell);
  107. }
  108.  
  109. void ThreadEventPairingHeap::return_cell(ThreadEventPairingHeapIndex cell)
  110.   storage[cell].sibling = freelist;
  111.   storage[cell].valid = 0;
  112.   freelist = cell;
  113.   elements--;
  114. }
  115.  
  116. void ThreadEventPairingHeap::make_room(int atLeast)
  117. {
  118.   if (freelist == ThreadEventPairingHeapIndex_NULL) 
  119.   {
  120.     if (allocatedSize > 0) 
  121.     {
  122.       ThreadEventPairingHeapIndex newSize = (allocatedSize * 3) / 2;
  123.  
  124.       ThreadEventPairingHeapRecord *newStorage = new ThreadEventPairingHeapRecord[newSize];
  125.       if (newStorage == 0)
  126.         error("make_room: out of space");
  127.       for (int i = 0; i < allocatedSize; ++i)
  128.       {
  129.         newStorage[i].item = storage[i].item;
  130.         newStorage[i].valid = storage[i].valid;
  131.         newStorage[i].sibling = storage[i].sibling;
  132.         newStorage[i].children = storage[i].children;
  133.       }
  134.       delete [allocatedSize] storage;
  135.       storage = newStorage;
  136.       for (i = allocatedSize; i < newSize; i++) 
  137.       {
  138.         storage[i].sibling = i+1;
  139.         storage[i].valid = 0;
  140.       }
  141.       storage[newSize-1].sibling = ThreadEventPairingHeapIndex_NULL;
  142.       freelist = allocatedSize;
  143.       allocatedSize = newSize;
  144.     } 
  145.     else 
  146.     {
  147.       if (atLeast <= MIN_STORAGE_SIZE) 
  148.         allocatedSize = MIN_STORAGE_SIZE;
  149.       else
  150.         allocatedSize = atLeast;
  151.       storage = new ThreadEventPairingHeapRecord[allocatedSize];
  152.       if (storage == 0)
  153.         error("make_room: out of space");
  154.       for (int i = 0; i < allocatedSize; i++) 
  155.       {
  156.         storage[i].sibling = i+1;
  157.         storage[i].valid = 0;
  158.       }
  159.       storage[allocatedSize-1].sibling = ThreadEventPairingHeapIndex_NULL;
  160.       freelist = 0;
  161.     }
  162.   }
  163. }
  164.  
  165. //
  166. //  make_child is not used since its
  167. //  code has now been directly encorporated into enq/del_front
  168. //
  169. // make_child takes two nodes and makes one the child of the other
  170. // and returns the index of the new parent. 
  171. //
  172. // We play fast and loose with the siblings field of a & b, although
  173. // we maintain the siblings of the children.
  174. //
  175. ThreadEventPairingHeapIndex ThreadEventPairingHeap::make_child(ThreadEventPairingHeapIndex a, 
  176.                                                ThreadEventPairingHeapIndex b)
  177. {
  178.   ThreadEventPairingHeapIndex parent;
  179.   ThreadEventPairingHeapIndex child;
  180.     
  181.   if (storage[a].item < storage[b].item)
  182.   {
  183.     parent = a; child = b;
  184.   } 
  185.   else 
  186.   {
  187.     parent = b; child = a;
  188.   }
  189.   //
  190.   // If the new parent has no children, simply add the new child.
  191.   // We assume that the child and the parent dont care about
  192.   // their *sibling* nodes
  193.   //
  194.   ThreadEventPairingHeapIndex popsKid = storage[parent].children;
  195.     
  196.   if (popsKid == ThreadEventPairingHeapIndex_NULL) 
  197.   {
  198.     storage[parent].children = child;
  199.     storage[child].sibling = child;
  200.   } 
  201.   else 
  202.   {
  203.     ThreadEventPairingHeapIndex temp = storage[popsKid].sibling;
  204.     storage[popsKid].sibling = child;
  205.     storage[child].sibling = temp;
  206.     storage[parent].children = child;
  207.   }
  208.   return(parent);
  209. }
  210.  
  211.  
  212. ThreadEventPairingHeapIndex ThreadEventPairingHeap::enq(ThreadEvent  item)
  213. {
  214.   ThreadEventPairingHeapIndex cell = get_cell();
  215.   
  216.   storage[cell].item = item;
  217.   storage[cell].children = ThreadEventPairingHeapIndex_NULL;
  218.   storage[cell].sibling = ThreadEventPairingHeapIndex_NULL;
  219.   
  220.   if (root == ThreadEventPairingHeapIndex_NULL) 
  221.     return root = cell;
  222.   else 
  223.   {
  224.     ThreadEventPairingHeapIndex parent;
  225.     ThreadEventPairingHeapIndex child;
  226.     
  227.     if ( storage[root].item <  storage[cell].item )
  228.     {
  229.       parent = root; child = cell;
  230.     } 
  231.     else 
  232.     {
  233.       parent = cell; child = root;
  234.     }
  235.     ThreadEventPairingHeapIndex popsKid = storage[parent].children;
  236.     
  237.     if (popsKid == ThreadEventPairingHeapIndex_NULL) 
  238.     {
  239.       storage[parent].children = child;
  240.       storage[child].sibling = child;
  241.     } 
  242.     else 
  243.     {
  244.       ThreadEventPairingHeapIndex temp = storage[popsKid].sibling;
  245.       storage[popsKid].sibling = child;
  246.       storage[child].sibling = temp;
  247.       storage[parent].children = child;
  248.     }
  249.     root = parent;
  250.     return cell;
  251.   }
  252. }
  253.  
  254. //
  255. //    Item removal is the most complicated routine.
  256. //
  257. //    We remove the root (should there be one) and then select a new
  258. //    root. The siblings of the root are in a circular list. We continue
  259. //    to pair elements in this list until there is a single element.
  260. //    This element will be the new root.
  261.  
  262. int ThreadEventPairingHeap::del_front()
  263. {
  264.   int valid = FALSE;
  265.   do 
  266.   {
  267.     if (root == ThreadEventPairingHeapIndex_NULL || elements <= 0) 
  268.       return(0);
  269.  
  270.     valid = storage[root].valid;
  271.     ThreadEventPairingHeapIndex child = storage[root].children;
  272.     return_cell(root);
  273.     
  274.     if (child == ThreadEventPairingHeapIndex_NULL)
  275.         root = ThreadEventPairingHeapIndex_NULL;
  276.     else 
  277.     {
  278.       while(storage[child].sibling != child) 
  279.       {
  280.         // We have at least two kids, but we may only have
  281.         // two kids. So, oneChild != child, but it is possible
  282.         // that twoChild == child.
  283.         
  284.         ThreadEventPairingHeapIndex oneChild = storage[child].sibling;
  285.         ThreadEventPairingHeapIndex twoChild = storage[oneChild].sibling;
  286.  
  287.         // Remove the two from the sibling list
  288.  
  289.         storage[child].sibling = storage[twoChild].sibling;
  290.         storage[oneChild].sibling = ThreadEventPairingHeapIndex_NULL;
  291.         storage[twoChild].sibling = ThreadEventPairingHeapIndex_NULL;
  292.         
  293.         ThreadEventPairingHeapIndex bestChild;
  294.         ThreadEventPairingHeapIndex worstChild;
  295.     
  296.         if (storage[oneChild].item < storage[twoChild].item) 
  297.         {
  298.           bestChild = oneChild; worstChild = twoChild;
  299.         } 
  300.         else 
  301.         {
  302.           bestChild = twoChild; worstChild = oneChild;
  303.         }
  304.         ThreadEventPairingHeapIndex popsKid = storage[bestChild].children;
  305.         
  306.         if (popsKid == ThreadEventPairingHeapIndex_NULL) 
  307.         {
  308.           storage[bestChild].children = worstChild;
  309.           storage[worstChild].sibling = worstChild;
  310.         } 
  311.         else 
  312.         {
  313.           ThreadEventPairingHeapIndex temp = storage[popsKid].sibling;
  314.           storage[popsKid].sibling = worstChild;
  315.           storage[worstChild].sibling = temp;
  316.           storage[bestChild].children = worstChild;
  317.         }
  318.         if (twoChild == child) 
  319.         {
  320.           // We have reduced the two to one, so we'll be exiting.
  321.           child = bestChild;
  322.           storage[child].sibling = child;
  323.         } 
  324.         else 
  325.         {
  326.           // We've removed two siblings, now we need to insert
  327.           // the better of the two
  328.           storage[bestChild].sibling = storage[child].sibling;
  329.           storage[child].sibling = bestChild;
  330.           child = storage[bestChild].sibling;
  331.         }
  332.       }
  333.       root = child;
  334.     }
  335.   } while ( !valid );
  336.  
  337.   return 1;
  338. }
  339.  
  340. int ThreadEventPairingHeap::del(ThreadEventPairingHeapIndex i) 
  341. {
  342.   if (storage[i].valid)
  343.   {
  344.     if (i == root)
  345.       del_front();
  346.     else
  347.     {
  348.       storage[i].valid = 0;
  349.       elements--;
  350.     }
  351.     return 1;
  352.   }
  353.   else
  354.     return 0;
  355. }
  356.  
  357. ThreadEventPairingHeapTrav::ThreadEventPairingHeapTrav(ThreadEventPairingHeap& a)
  358. {
  359.   h = &a;
  360.   for (current = 0; current < h->allocatedSize; current++) 
  361.     if (h->storage[current].valid)
  362.         return;
  363.   current = ThreadEventPairingHeapIndex_NULL;
  364. }
  365.  
  366. void ThreadEventPairingHeapTrav::del()
  367. {
  368.   if (current == ThreadEventPairingHeapIndex_NULL)
  369.     h->error("del of null traverser");
  370.   h->del(current);
  371. }
  372.  
  373. void ThreadEventPairingHeapTrav::advance()
  374. {
  375.   if (current == ThreadEventPairingHeapIndex_NULL)
  376.     return;
  377.   
  378.   for (current++; current < h->allocatedSize; current++) 
  379.     if (h->storage[current].valid)
  380.         return;
  381.   current = ThreadEventPairingHeapIndex_NULL;
  382. }
  383.  
  384. @
  385.